package com.jsh.erp.session;

import com.jsh.erp.datasource.entities.Tenant;
import com.jsh.erp.datasource.entities.User;
import com.jsh.erp.service.tenant.TenantService;
import com.jsh.erp.utils.ObjectMapperUtils;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

@Component
public class UserSessionManager {

    final String userSessionPreFix="user:session:";

    final String headerSessionId="x-session-id";

    @Resource
    StringRedisTemplate redisTemplate;


    @Resource
    private TenantService tenantService;



    public void saveSession(User user) throws Exception{
        HttpServletRequest request =((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        if(user.getTenantId()!=null) {
            Tenant tenant = tenantService.getTenantByTenantId(user.getTenantId());
            if(tenant!=null) {
                Long tenantId = tenant.getTenantId();
                Integer userNumLimit = tenant.getUserNumLimit();
                Integer billsNumLimit = tenant.getBillsNumLimit();
                if(tenantId!=null) {
                    request.getSession().setAttribute("tenantId",tenantId); //租户tenantId
                    request.getSession().setAttribute("userNumLimit",userNumLimit); //用户限制数
                    request.getSession().setAttribute("billsNumLimit",billsNumLimit); //单据限制数
                }
            }
        }
        String sessionId=buildSessionId(user.getId()+"",user.getLoginame());

        request.getSession().setAttribute(sessionId,user);

        //保存到redis
        String redisKey=userSessionPreFix+sessionId;

        String userJson= ObjectMapperUtils.writeToJsonString(user);

        redisTemplate.opsForValue().set(redisKey, userJson, 18, TimeUnit.HOURS);

        HttpServletResponse response =((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();

        response.setHeader(headerSessionId,sessionId);
        request.getSession().setAttribute(headerSessionId,sessionId);

    }


    public Object getSessionUserWithCache(){

        HttpServletRequest request =((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();

        String sessionId =(String) request.getSession().getAttribute(headerSessionId);
        if(StringUtils.isEmpty(sessionId)){
            sessionId=request.getHeader(headerSessionId);

            if(!StringUtils.isEmpty(sessionId)){
                request.getSession().setAttribute(headerSessionId,sessionId);
            }
        }

        String redisKey=userSessionPreFix+sessionId;

        Object userInfo = request.getSession().getAttribute(sessionId);

        if(userInfo==null){

           String userJson= redisTemplate.opsForValue().get(redisKey);

           if(!StringUtils.isEmpty(userJson)){
               userInfo = ObjectMapperUtils.readFromJsonString(userJson,User.class);
               request.getSession().setAttribute(sessionId,userInfo);
               request.getSession().setAttribute(headerSessionId,sessionId);
           }
        }

        if(userInfo==null){
            return null;
        }

        String userJson= ObjectMapperUtils.writeToJsonString(userInfo);
        redisTemplate.opsForValue().set(redisKey, userJson, 18, TimeUnit.HOURS);

        return userInfo;
    }

    public User getSessionUser(){
        HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
        String sessionId=request.getHeader(headerSessionId);

        if(StringUtils.isEmpty(sessionId)){
            sessionId =(String) request.getSession().getAttribute(headerSessionId);
        }

        if(StringUtils.isEmpty(sessionId)){
            return null;
        }

        return (User)request.getSession().getAttribute(sessionId);
    }

    public User getSessionUser(String sessionId){
        if(StringUtils.isEmpty(sessionId)){
            return null;
        }
        HttpServletRequest request =((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        return (User)request.getSession().getAttribute(sessionId);
    }


    public void cleanSession(){
        HttpServletRequest request =((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        User sessionUser=getSessionUser();

        if(sessionUser!=null){
            String sessionId=request.getHeader(headerSessionId);

            if(StringUtils.isEmpty(sessionId)){
                sessionId =(String) request.getSession().getAttribute(headerSessionId);
            }

            if(StringUtils.isEmpty(sessionId)){
                return;
            }

            request.getSession().removeAttribute(sessionId);
            request.getSession().removeAttribute(headerSessionId);

            String redisKey=userSessionPreFix+sessionId;
            redisTemplate.delete(redisKey);

        }
        request.getSession().removeAttribute("tenantId");
        request.getSession().removeAttribute("userNumLimit");
        request.getSession().removeAttribute("billsNumLimit");

    }

    private String buildSessionId(String userId,String userName){
        return userId+"X"+ UUID.randomUUID();
    }

}
